Variadic Templates : C++
About
任意の数の引数をテンプレートへ渡すことが出来る機能.
Usecase
任意の数の引数を取り, 1つずつtypeidを出力する例
code:cpp
// 引数が0になったときに呼び出される関数
void print_type()
{
std::cout << std::endl;
}
// 引数が0以上の場合に使用される関数
template<typename T, typename ...Ts>
void print_type(T head, Ts... body)
{
std::cout << "typeid : " << typeid(head).name() << std::endl;
// 再帰的な呼び出し
// 呼び出しごとにbodyの先頭がheadとして消費されるため, 引数はやがて0となる
// 0 : function(head, body...) => headに対して処理を行う
// 1 : function(body...) => 与えられたbodyを引数に再帰呼び出しを行う
// 2 == 0 : function(head, body...) => 1. で与えられたbodyの先頭がheadとして再解釈される.
print_type(body...);
// extra
// sizeof...()により要素数を取得できる
}
// 非型テンプレートパラメーターも使用可能
template<foo... f>
std::vector<foo> make_foo_vector()
{
return std::vector<foo> {f..};
}
ぼくは親切なので図解しておく
https://scrapbox.io/files/65ffb8ca4cff0700263a473b.png
HaskellにおけるListのhead/tailとその再帰呼び出しに似ている
というか, そのもの
Expansion of Parameter Packs
code:cpp
// 関数テンプレートにおける展開
template<typename ...Ts>
void function(Ts ...ts) {};
// Initializer Listにおける展開
template<typename T, typename ...Args>
void function(Args ...args)
{
T t[] = {args...};
}
// 可変引数テンプレートへ展開
template<typename ...Ts>
class foo;
template<typename ...Ts>
class bar
{
foo<Ts...> f;
};
Applies the Process to the Entire Element
code:cpp
// map()のように, 要素全体へ処理を適用する
function(sizeof(foo)...); // fooの要素一つずつにsizeof()を適用したものをfunction()へ渡す